package skiree.host.abetsy.api.annotation;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import skiree.host.abetsy.api.service.global.GlobalDIYService;
import skiree.host.abetsy.dao.LocalAnimeMapper;
import skiree.host.abetsy.model.LocalAnime;
import skiree.host.abetsy.model.LocalEpisode;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Service
public class EventQueueServerImpl implements EventQueueServer {

    @Resource
    private GlobalDIYService globalDIYService;

    @Resource
    private LocalAnimeMapper localAnimeMapper;

    @Override
    public Object addToEventQueue(EventQueueModel queueModel) {
        ThreadPoolUtil.getInstance().addToEventQueue(queueModel);
        return null;
    }

    @Override
    public void SettingExecutor(int coreSize, int maxSize) {
        ThreadPoolUtil.getInstance().SettingExecutor(coreSize, maxSize);
    }

    @Override
    public Map<Integer, EventQueueModel> getQueueModelWaitingMap() {
        return ThreadPoolUtil.getInstance().getEventQueueWaiting();
    }

    @Override
    public Map<EventQueueModel, Future<?>> getQueueModelDoingMap() {
        return ThreadPoolUtil.getInstance().getEventQueueDoing();
    }

    @Override
    public void doEvent() {
        if (ThreadPoolUtil.getInstance().getExecutor().getActiveCount() < ThreadPoolUtil.getInstance().getMaxSize()) {
            // 此时可以放入新的可执行任务
            int putNum = ThreadPoolUtil.getInstance().getMaxSize() - ThreadPoolUtil.getInstance().getExecutor().getActiveCount();
            List<Map.Entry<Integer, EventQueueModel>> entriesToRemove = getQueueModelWaitingMap().entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .limit(putNum).collect(Collectors.toList());
            entriesToRemove.forEach(entry -> getQueueModelWaitingMap().remove(entry.getKey()));
            entriesToRemove.forEach(entry -> {
                entry.getValue().setQueueStatus(EventQueueStatus.Doing);
                Future<?> future = ThreadPoolUtil.getInstance().getExecutor().submit(() -> {
                    try {
                        LocalEpisode localEpisode = new LocalEpisode();
                        BeanUtil.copyProperties(entry.getValue(), localEpisode);
                        globalDIYService.doEventInPool(localEpisode);
                        return 1;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        getQueueModelDoingMap().remove(entry.getValue());
                    }
                    return null;
                });
                getQueueModelDoingMap().put(entry.getValue(), future);
            });
        }
    }

    @Override
    public EventQueueModel initEventQueue(LocalEpisode localEpisode) {
        QueryWrapper<LocalAnime> animeQueryWrapper = new QueryWrapper<>();
        animeQueryWrapper.eq("id", localEpisode.getAnimeId());
        LocalAnime selectOne = localAnimeMapper.selectOne(animeQueryWrapper);
        if (selectOne == null) return null;
        // 复制属性
        EventQueueModel queueModel = new EventQueueModel();
        BeanUtil.copyProperties(localEpisode, queueModel);
        queueModel.setAnimeId(localEpisode.getAnimeId());
        queueModel.setAnimeTitle(selectOne.getTitle());
        queueModel.setQueueStatus(EventQueueStatus.Waiting);
        queueModel.setDoingSize(0);
        queueModel.setWaitingSize(0);
        queueModel.setQueueSize(0);
        return queueModel;
    }

}
